#pragma once

#define MSG_HELLO WM_USER + 0x318
#define MSG_FILTER_SEND WM_USER + 0x401
#define MSG_FILTER_SENDTO WM_USER + 0x402
#define MSG_FILTER_RECV WM_USER + 0x403
#define MSG_FILTER_RECVFROM WM_USER + 0x404
#define MSG_FILTER_WSASEND WM_USER + 0x405
#define MSG_FILTER_WSARECV WM_USER + 0x406
#define MSG_FILTER_WSARECVFROM WM_USER + 0x407
#define MSG_FILTER_CONNECT WM_USER + 0x408
#define MSG_NOTICE_WSAGETOVERLAPPEDRESULT WM_USER + 0x451
#define MSG_NOTICE_WSARECV WM_USER + 0x452
#define MSG_CHECK_AVAILABLE_CACHE_DATA WM_USER + 0x500
#define MSG_GET_AVAILABLE_CACHE_DATA WM_USER + 0x501
#define MSG_NOTICE_CREATEPROCESSASUSER WM_USER + 0x502

#include <WinSock2.h>
#include <WinSock.h>

extern "C" _declspec(dllexport) VOID WINAPI SetMainAppHwnd(HWND hWnd);
extern "C" _declspec(dllexport) VOID WINAPI Test(ULONG slong);

enum WinsockHookType
{
	WHT_CONNECT,
	WHT_SEND,
	WHT_SENDTO,
	WHT_RECV,
	WHT_RECVFROM,
	WHT_WSASEND,
	WHT_WSARECV,
	WHT_WSARECVFROM,
	WHT_NOTICE_WSARECV,
	WHT_NOTICE_WSAGETOVERLAPPEDRESULT
};

enum ReceivedDataStatus
{
	DataReceived,
	EmptyBuffer,
	NoMoreData
};

enum HookingStatus
{
	MAINAPP = 0x10,
	INSTALLHOOK,
	UNINSTALLHOOK,
	NULLMSGHWND
};

typedef struct StructWinsockHookMsg
{
	WinsockHookType hookType;
	WinsockHookType overlappedHookType;
	SOCKET sockRelated;
	PUCHAR lpData;
	DWORD uDataSharedMemoryName;
	DWORD uDataLength;
	int nFlags;
	LPWSAOVERLAPPED lpOverlapped;
	LPWSABUF lpWSABuffers;
	DWORD dwBufferCount;
	DWORD_PTR lpCompletionRoutine;
	struct sockaddr socketAddr;
	WSAOVERLAPPED WSAOverlapped;
}WINSOCKHOOKMSG, *PWINSOCKHOOKMSG;

typedef struct StructCacheDataMsg
{
	SOCKET sockRelated;
	DWORD nDataLength;
	UCHAR lpData[1024000];
}CACHEDATAMSG, *PCACHEDATAMSG;

class CWSABufferInfo;

INT SayHelloToMainApp();

// Internal used
BOOL Filter_connect(SOCKET s, const struct sockaddr FAR * name, int namelen);
BOOL Filter_send(SOCKET s, const char FAR *buf, int len, int flags);
BOOL Filter_sendto(SOCKET s, const char FAR *buf, int len, int flags,const struct sockaddr* to, int tolen);
BOOL Filter_recv(SOCKET s, char FAR *buf, int len, int flags);
BOOL Filter_WSASend(SOCKET s, LPWSABUF lpBuffers, 
	DWORD dwBufferCount, LPDWORD lpNumberOfBytesSent, DWORD dwFlags, 
	LPWSAOVERLAPPED lpOverlapped, 
	LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine);
BOOL Filter_recvfrom(SOCKET s, char* buf, int len, int flags, struct sockaddr* from, int* fromlen);
BOOL Filter_WSARecv(
	SOCKET s,                                               
	LPWSABUF lpBuffers,                                     
	DWORD dwBufferCount,                                    
	LPDWORD lpNumberOfBytesRecvd,                           
	LPDWORD lpFlags,                                        
	LPWSAOVERLAPPED lpOverlapped,                           
	LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine  
	);
BOOL Filter_WSARecvFrom(
	SOCKET s,                                               
	LPWSABUF lpBuffers,                                     
	DWORD dwBufferCount,                                    
	LPDWORD lpNumberOfBytesRecvd,                           
	LPDWORD lpFlags,                                        
	struct sockaddr FAR *lpFrom,                            
	LPINT lpFromlen,                                        
	LPWSAOVERLAPPED lpOverlapped,                           
	LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine  
	);
INT CheckAvailableCacheData(SOCKET s);
INT GetAvailableCacheData(SOCKET s, PUCHAR lpData, INT nMaxSize);
BOOL Notice_WSARecv(SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,                                    
		LPDWORD lpNumberOfBytesRecvd, LPDWORD lpFlags, LPWSAOVERLAPPED lpOverlapped,
		LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine);
BOOL Notice_WSAGetOverlappedResult(SOCKET s, LPWSAOVERLAPPED lpOverlapped, 
	LPDWORD lpcbTransfer, BOOL fWait, LPDWORD lpdwFlags, CWSABufferInfo* pBufferInfo);
INT CreateProcessInform(INT nOldProcessID, int nNewProcessID);